classdef Population < handle
    %UNTITLED5 Summary of this class goes here
    %   Detailed explanation goes here
    
    properties
        individuals
        sorted = false
        IndividualsClass % not worknig, creates instance
        size
        best_of_all;
        pattern
        next_generation
        stops
        
        Crosser
        ParentChooser
        %GenerationCreator
        GenerationChanger
        
        %b = 1000000000000;
    end
    
    methods
        
        function obj = Population(varargin)
            obj.best_of_all = [];
            if nargin==2
                size = varagrin{1}
                IndividualsClass = varargin{2}
                %obj.individuals = zeros(size);
                for k=1:size
                    obj.individuals = [obj.individuals IndividualsClass.generate_individual()];
                end
                obj.IndividualsClass = IndividualsClass;
                obj.size = size;
            else
                obj.individuals = [];
            end
            
        end
        function compute_objectives(pop)
            for k=1:pop.size
                pop.individuals(k).compute_objective();
            end
        end
        
        function sort(pop)
            [~,idx]=sort([pop.individuals.objective_value]);
            pop.individuals = pop.individuals(idx);
            pop.sorted = true;
            
            if(isempty(pop.best_of_all))
                pop.best_of_all = pop.individuals(1);
            else
                if(pop.individuals(1).objective_value <  pop.best_of_all.objective_value)
                    pop.best_of_all = pop.individuals(1);
                end
            end
        end
        
        function ind = best(pop)
            if pop.sorted
                ind = pop.individuals(1);
            else
                [~,idx]=min([pop.individuals.objective_value]);
                ind = pop.individuals(idx);
                
                
            end
            
        end
        
        function ind = worst(pop)
            if pop.sorted
                ind = pop.individuals(pop.size);
            else
                [~,idx]=max([pop.individuals.objective_value]);
                ind = pop.individuals(idx);
                
                
            end
            
        end
        
        function ind = mean_objective_value(pop)
            ind = mean([pop.individuals.objective_value]);
        end
        
        function inds = inds_get(pop)
            inds = pop.individuals;
        end
        
        
        
        %refactoring stuff
        

        function create_children(obj)
            
            ps = obj.ParentChooser.execute(obj);
            
            chs = obj.Crosser.execute(obj, ps);
            
            obj.next_generation = [obj.next_generation chs];
            %obj.GenerationCreator.execute(obj, chs)
            
        end
        
        function to_next_generation(obj)
            
            obj.GenerationChanger.execute(obj)
            
            obj.next_generation = [];
            obj.sorted = false; 
            
        end
        
        function generate_random_pattern(obj)
            density = 0.5; %TODO: refactor
            obj.pattern = random_connections( obj.stops.number, density ); %I don't like this. TODO: find better way to get number of stops
        end
        
        function calibrate(obj)
            calibration_individual = obj.IndividualsClass.new(obj);
            bb = 0;
            for i=1:20
            %calibration_individual.connections = one_path_connection(obj); % think about better reference (maybe star?)
            calibration_individual.connections = obj.IndividualsClass.generate_individual(obj).connections;
            calibration_individual.compute_objective();
            
            cost_part = calibration_individual.total_cost;
            people_distance_part = calibration_individual.objective_value - calibration_individual.total_cost;
            
            bb = bb + (calibration_individual.stala * people_distance_part) / cost_part;
            end
            obj.IndividualsClass.b = bb /20;
        end
        
        function clear(obj)
            
            obj.individuals = [];
            obj.sorted = false;
            obj.next_generation = [];
            for k=1:obj.size
                obj.individuals = [obj.individuals obj.IndividualsClass.generate_individual(obj)];
            end
            
            obj.best_of_all = [];
        end
        
    end
    
end

